//////////////////////////////////////////////////////////////////////////////////
//                                                                              //
//  This file is part of the buola project (https://code.google.com/p/buola/).  //
//                                                                              //
//  Copyright(c) 2007-2012 Xavi Gratal                                          //
//  gratal AT gmail DOT com                                                     //
//                                                                              //
//  Buola is free software: you can redistribute it and/or modify               //
//  it under the terms of the GNU General Public License as published by        //
//  the Free Software Foundation, either version 3 of the License, or           //
//  (at your option) any later version.                                         //
//                                                                              //
//  Buola is distributed in the hope that it will be useful,                    //
//  but WITHOUT ANY WARRANTY; without even the implied warranty of              //
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               //
//  GNU General Public License for more details.                                //
//                                                                              //
//  You should have received a copy of the GNU General Public License           //
//  along with buola.  If not, see <http://www.gnu.org/licenses/>.              //
//                                                                              //
//////////////////////////////////////////////////////////////////////////////////

#include <buola/os/path.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <buola/os/cenv.h>
#include <buola/io/curi.h>
#include <buola/io/cfile.h>
#include <buola/algorithm/split.h>

namespace buola { namespace os {

static std::vector<io::CURI> sPath;
static std::string sLastPath;

static void update_path()
{
    std::string lPath=CEnv::Get("PATH");
    if(lPath==sLastPath&&!sPath.empty()) return;
    sLastPath=lPath;
    sPath.clear();
    
    if(lPath.empty())
    {
        sPath.push_back(io::file("/bin"));
        sPath.push_back(io::file("/usr/bin"));
        return;
    }
    
    std::vector<std::string> lElements;
    split(lPath,lElements,fn::equal_to(':'),nDeleteEmpty);

    for(auto &i : lElements)
    {
        sPath.push_back(io::file(i));
    }
}
    
const std::vector<io::CURI> &get_path()
{
    update_path();
    return sPath;
}

io::CURI get_command(const std::string &pCmd)
{
    if(pCmd.find('/')!=std::string::npos) //the file contains a / and we should use it as is
    {
        io::CURI lURI=io::file(pCmd);
        try
        {
            io::CFile lFile(lURI);
            ///\todo ignore link and go directly to file
            if((lFile.IsRegular()||lFile.IsLink())&&lFile.CanExecute())
                return lURI;
        }
        catch(...) {}

        return io::CURI();
    }
    else
    {
        update_path();
    
        io::CURI lBest;
        for(auto &i : sPath)
        {
            io::CURI lURI=i/pCmd;
            try
            {
                io::CFile lFile(lURI);

                if(!(lFile.IsRegular()||lFile.IsLink()))
                    continue;

                if(lFile.CanExecute())
                    return lURI;

                if(lBest.empty())
                    lBest=lURI;
            }
            catch(...) {}
        }

        return lBest;
    }    
}

/*namespace os */ } /*namespace buola*/ }
